# -*-coding:utf-8-*-
import os
import sys
import json
import socket
import shutil
try:
    import hou
except Exception as TEST_ERR:
    print('import hou testing')
# import hou
import threading
from PySide2.QtGui import *
from PySide2.QtCore import *
from PySide2.QtWidgets import *

"""
该文件是houdini客户端脚本，安装在houdini中，实现的功能是从服务器中获取项目、集数、镜头信息，
同时获取到该镜头相关联的跟踪、动画文件。能下载这些文件到本地目录，下载后可导入houdini
该文件还能实现houdini的工程文件版本自动规则命名以及版本升级，以及导入已有的版本工程
"""


class ExistDialog(QDialog):
    """
    保存houdini工程以及版本升级
    """
    def __init__(self,file_path):
        super(ExistDialog, self).__init__()
        self.file_path=file_path
        self.setWindowTitle('版本已存在')
        self.main_layout=QHBoxLayout()
        self.new_version_label=QLabel('custom version:')
        self.new_verison_edit=QLineEdit()
        rex=QRegExp("[0-9\.]+$")
        rv=QRegExpValidator(rex,self)
        self.new_verison_edit.setValidator(rv)
        self.new_verison_edit.setText('0')
        self.OK_btn=QPushButton('OK')
        self.OK_btn.clicked.connect(self._save)
        self.cover_btn=QPushButton('Cover')
        self.cover_btn.clicked.connect(self._cover)
        self.main_layout.addWidget(self.new_version_label)
        self.main_layout.addWidget(self.new_verison_edit)
        self.main_layout.addWidget(self.OK_btn)
        self.main_layout.addWidget(self.cover_btn)
        self.setLayout(self.main_layout)

    def int2str(self,number):
        if number < 10:
            return 'v00' + str(number)
        elif number < 100:
            return 'v0' + str(number)
        else:
            return 'v' + str(number)

    def update_version(self,ori_version,new_num):
        new_file_name = ''
        file_name, ex_name = os.path.splitext(ori_version)
        slite_files = file_name.split('_')
        vers = slite_files[-1]
        slite_files.remove(vers)
        if vers.startswith('v'):
            num = vers[1:]
            new_ver = new_num
            version = self.int2str(new_ver)
            slite_files.append(version)
            new_file_name = '_'.join(slite_files) + ex_name
        else:
            new_file_name = file_name + '_v001' + ex_name
        return new_file_name

    def _save(self):
        int_new_version=int(self.new_verison_edit.text())
        # new_version=self.int2str(int_new_version)
        dir_path,file_name=os.path.split(self.file_path)
        new_file_name=self.update_version(file_name,int_new_version)
        print(new_file_name)
        new_file=os.path.join(dir_path,new_file_name)
        if os.path.exists(new_file):
            QMessageBox.information(self,'已存在','该{}版本已存在'.format(new_file_name))
        else:
            hou.hipFile.save(new_file)
            self.close()

    def _cover(self):
        int_new_version=int(self.new_verison_edit.text())
        dir_path,file_name=os.path.split(self.file_path)
        new_file_name=self.update_version(file_name,int_new_version)
        new_file=os.path.join(dir_path,new_file_name)
        hou.hipFile.save(new_file)
        self.close()

class Name(QWidget):
    """
    重命名hip文件
    """
    name_Signal = Signal(str)

    def __init__(self):
        super(Name, self).__init__()
        self.main_layout = QVBoxLayout()
        self.name_label = QLabel('New Name:')
        self.name_edit = QLineEdit()
        self.name_btn = QPushButton('OK')
        self.name_btn.clicked.connect(self._set_name)
        self.main_layout.addWidget(self.name_label)
        self.main_layout.addWidget(self.name_edit)
        self.main_layout.addWidget(self.name_btn)
        self.setLayout(self.main_layout)

    def _set_name(self):
        name = self.name_edit.text()
        if name:
            self.name_Signal.emit(name)
            self.close()

class ListModel(QListWidget):
    """
    列表模型，可以生成项目列表与镜头列表
    """
    data_Signal=Signal(dict)
    def __init__(self):
        super(ListModel, self).__init__()
        # self.clicked.connect(self._show_info)
        self.setWindowFlags(Qt.WindowStaysOnTopHint)
        self.doubleClicked.connect(self._show_info)
        self.data={}
    def set_data(self,data):
        """
        :param data:
        :return:
        """
        if data:
            self.clear()
            self.data=data
            for k,v in data.items():
                item=QListWidgetItem()
                item.setText(k)
                item.setTextAlignment(Qt.AlignCenter)
                self.addItem(item)
            self.sortItems()

    def _show_info(self,index):
        item=self.itemFromIndex(index)
        text=item.text()
        result=self.data[text] if text in self.data.keys() else {'description': '', 'entity_name': text, 'img_path': 'path', 'frame': '0'}
        self.data_Signal.emit(result)
        # print(self.data[text])
        self.close()

    def filter_item(self,text):
        try:
            # item_list=[]
            for i in range(self.count()):
                item=self.item(i)
                project_name=item.text()
                if text not in project_name:
                    item.setHidden(True)
        except Exception as filter_item_ERR:
            print(str(filter_item_ERR))

    def add_asset(self,asset_name):
        item=QListWidgetItem()
        item.setText(asset_name)
        item.setTextAlignment(Qt.AlignCenter)
        self.addItem(item)

    def show_all(self):
        for i in range(self.count()):
            item = self.item(i)
            item.setHidden(False)

class ShotListWindow(QDialog):
    """
    镜头列表，显示所有获取到的镜头信息
    """
    shot_Signal=Signal(dict)
    def __init__(self):
        super(ShotListWindow, self).__init__()
        self.setWindowFlags(Qt.WindowStaysOnTopHint)
        self.btn_style="""QPushButton{color:black}
                                  QPushButton:hover{color:red}
                                 QPushButton{background-color:#A9A9A9}
                                  QPushButton{border:2px}
                                  QPushButton{border-radius:3px}
                                  QPushButton{padding:1px 1px}"""
        self.setWindowTitle('Shots')
        self.main_layout=QVBoxLayout()
        self.search_layout=QHBoxLayout()
        self.search_edit=QLineEdit()
        self.search_edit.textEdited.connect(self._text_edited)
        self.search_btn=QPushButton('search')
        self.search_btn.clicked.connect(self._filter_shot)
        self.search_btn.setStyleSheet(self.btn_style)
        self.add_btn=QPushButton('create')
        self.add_btn.clicked.connect(self._add_asset)
        self.add_btn.setStyleSheet(self.btn_style)
        self.search_layout.addWidget(self.search_edit)
        self.search_layout.addWidget(self.search_btn)
        self.search_layout.addWidget(self.add_btn)
        self.shot_list=ListModel()
        self.shot_list.data_Signal.connect(self._get_shot)
        self.main_layout.addLayout(self.search_layout)
        self.main_layout.addWidget(self.shot_list)
        self.setLayout(self.main_layout)

    def set_data(self,data):
        if data:
            print('shots data:',data)
            self.shot_list.set_data(data)

    def _filter_shot(self):
        """
        filter shot
        :return:
        """
        text = self.search_edit.text()
        if text:
            self.shot_list.filter_item(text)

    def _add_asset(self):
        text = self.search_edit.text()
        if text:
            self.shot_list.add_asset(text)

    def _text_edited(self, ha):
        if not ha:  # 当没有搜索内容时，就重置
            # self.create_items(self.data_list)
            self.shot_list.show_all()


    def _get_shot(self,data):
        self.shot_Signal.emit(data)
        self.close()

class FileListMode(QListWidget):
    """
    文件列表模型，显示cgtw上跟踪与动画的文件
    """
    path_Signal=Signal(str)
    def __init__(self):
        super(FileListMode, self).__init__()
        self.clicked.connect(self._select_path)
        self.data={}  # {'file_dir_name':path,}

    def set_data(self,data):
        if data:
            self.clear()
            self.data=data
            for k,v in data.items():
                item=QListWidgetItem()
                item.setText(k)
                self.addItem(item)
            self.sortItems()

    def _select_path(self,index):
        # print(index)
        item=self.itemFromIndex(index)
        file_name=item.text()
        path=self.data[file_name]
        self.path_Signal.emit(path)

class PipelineTab(QDialog):
    """
    阶段信息窗口，显示相关阶段跟踪，动画的文件信息
    """
    def __init__(self):
        super(PipelineTab, self).__init__()

        self.current_selected_path=''

        self.btn_style= """QPushButton{color:black}
                                  QPushButton:hover{color:red}
                                 QPushButton{background-color:#A9A9A9}
                                  QPushButton{border:2px}
                                  QPushButton{border-radius:3px}
                                  QPushButton{padding:1px 1px}"""

        self.setWindowTitle('获取阶段资源')
        self.main_layout=QVBoxLayout()
        self.main_layout.setSpacing(20)
        self.pipeline_layout=QHBoxLayout()
        self.mm_layout=QVBoxLayout()
        self.mm_label=QLabel('mm')
        self.mm_label.setAlignment(Qt.AlignCenter)
        self.mm_list=FileListMode()
        self.mm_list.path_Signal.connect(self._get_path)
        self.mm_layout.addWidget(self.mm_label)
        self.mm_layout.addWidget(self.mm_list)
        self.ani_layout=QVBoxLayout()
        self.ani_label=QLabel('ani')
        self.ani_label.setAlignment(Qt.AlignCenter)
        self.ani_list=FileListMode()
        self.ani_list.path_Signal.connect(self._get_path)
        self.ani_layout.addWidget(self.ani_label)
        self.ani_layout.addWidget(self.ani_list)
        self.abc_layout=QVBoxLayout()
        self.abc_label = QLabel('abc')
        self.abc_label.setAlignment(Qt.AlignCenter)
        self.abc_dir_layout=QVBoxLayout()
        self.abc_dir_list = FileListMode()
        self.abc_dir_list.path_Signal.connect(self._get_abc_dir_path)
        self.abc_list=FileListMode()
        self.abc_list.path_Signal.connect(self._get_path)
        self.abc_layout.addWidget(self.abc_label)
        self.abc_layout.addWidget(self.abc_dir_list)
        self.abc_layout.addWidget(self.abc_list)

        self.env_layout=QVBoxLayout()
        self.env_label=QLabel('env')
        self.env_label.setAlignment(Qt.AlignCenter)
        self.env_list=FileListMode()
        self.env_list.path_Signal.connect(self._get_path)
        self.env_layout.addWidget(self.env_label)
        self.env_layout.addWidget(self.env_list)

        self.btn_layout=QHBoxLayout()
        self.open_dir_btn=QPushButton('打开目录')
        self.open_dir_btn.clicked.connect(self._open_dir)
        self.open_dir_btn.setStyleSheet(self.btn_style)
        self.load_btn=QPushButton('下载')
        self.load_btn.clicked.connect(self._load)
        self.load_btn.setStyleSheet(self.btn_style)
        self.import_btn=QPushButton('导入')
        self.import_btn.clicked.connect(self._import_file)
        self.import_btn.setStyleSheet(self.btn_style)
        self.btn_layout.addWidget(self.open_dir_btn)
        self.btn_layout.addWidget(self.load_btn)
        self.btn_layout.addWidget(self.import_btn)
        self.pipeline_layout.addLayout(self.mm_layout)
        self.pipeline_layout.addLayout(self.ani_layout)
        self.pipeline_layout.addLayout(self.abc_layout)
        self.pipeline_layout.addLayout(self.env_layout)
        self.main_layout.addLayout(self.pipeline_layout)
        self.main_layout.addLayout(self.btn_layout)
        self.setLayout(self.main_layout)

    def init_pipeline_source(self,data):
        if data:
            for k,v in data.items():
                if k=='mm':
                    self.mm_list.set_data(v)
                if k=='ani':
                    self.ani_list.set_data(v)
                if k == 'abc':
                    self.abc_dir_list.set_data(v)
                if k=='env':
                    self.env_list.set_data(v)

    def _get_path(self,path):
        print(path)
        self.current_selected_path=path

    def _get_abc_dir_path(self,path):
        """
        select abc director
        :param path:
        :return:
        """
        print(path)
        self.current_selected_path=path
        data = {}
        if os.path.exists(path):
            file_list = os.listdir(path)#这里是文件夹列表
            for i in file_list:
                if i.endswith('.ma') or i.endswith('.abc') or i.endswith('.matInfo') and not i.startswith('.'):
                    data[i] = os.path.join(path, i)
        self.abc_list.set_data(data)

    # def _get_ani(self,ani_path):
    #     print(ani_path)
    #
    # def _get_env(self,env_path):
    #     print(env_path)


    def _open_dir(self):
        if self.current_selected_path:
            rp = self.current_selected_path.replace("/", "\\")
            if os.path.isfile(self.current_selected_path):
                rp=os.path.split(rp)[0]
            try:
                os.popen(r"explorer.exe  %s" % rp)
            except Exception as _open_dir_ERR:
                print(str(_open_dir_ERR))

    def _load(self):
        if self.current_selected_path:
            ordir,file_name=os.path.split(self.current_selected_path)
            # dir = QFileDialog.getExistingDirectory(self, '选择目录',dir=hou.getenv('JOB'))#,dir=hou.getenv('JOB')
            if file_name.endswith('.fbx'):
                dir=os.path.join(hou.getenv('JOB'),'fbx')
            else:# file_name.endswith('.abc'):
                dir=os.path.join(hou.getenv('JOB'),'abc')
            print('_load:',dir)
            if dir:
                new_path=os.path.join(dir,file_name)
                print('current_selected_path:',self.current_selected_path)
                print('new_path:',new_path)
                try:
                    if os.path.exists(new_path):
                        if os.path.isfile(self.current_selected_path):
                            if os.path.exists(new_path):
                                os.remove(new_path)
                                shutil.copy(self.current_selected_path,new_path)
                        elif os.path.isdir(self.current_selected_path):
                            if os.path.exists(new_path):
                                shutil.rmtree(new_path)
                                shutil.copytree(self.current_selected_path,new_path)
                    else:
                        if os.path.isfile(self.current_selected_path):
                            shutil.copy(self.current_selected_path, new_path)
                        elif os.path.isdir(self.current_selected_path):
                            shutil.copytree(self.current_selected_path, new_path)
                    QMessageBox.information(None, 'Download','下载完成')

                except Exception as _load_ERR:
                    print(str(_load_ERR))
                    QMessageBox.information(None,'erro',str(_load_ERR))

    def _create_abc(self,abcpath):
        abc=None
        if os.path.exists(abcpath):
            dir_path,file_name=os.path.split(abcpath)
            name=os.path.splitext(file_name)[0]
            root=hou.node('/obj')
            abc=root.createNode('alembicarchive',name)
            job_path=hou.getenv('JOB')
            abcpath='$JOB'+abcpath[len(job_path):]
            abc.parm('fileName').set(abcpath)
            abc.parm('buildHierarchy').pressButton()
        return abc

    def _create_abc_merge(self,abc_node):
        # merg=None
        root = hou.node('/obj')
        name = abc_node.name()
        newName = name + 'Geo'
        Geo = root.createNode('geo', newName)
        Geo.setInput(0,abc_node)
        Geo.setGenericFlag(hou.nodeFlag.Display, 0)
        abc_pos=abc_node.position()
        Geo.setPosition(hou.Vector2(abc_pos[0],abc_pos[1]-1))
        abcChildren1=abc_node.children()
        sn=[]
        for c in abcChildren1:
            abcChildren1geo = c.children()[0]
            abcChildren1geo1shape = abcChildren1geo.children()[0]
            abcChildren1geo1shapePath = abcChildren1geo1shape.path()
            abcChildren1geo1shapeName = abcChildren1geo1shape.name()

            objmerge = Geo.createNode('object_merge', 'object_merge' + abcChildren1geo1shapeName)
            objmerge.parm('objpath1').set(abcChildren1geo1shapePath)
            objmerge.parm('xformtype').set(1)
            sn.append(objmerge)

        merge = Geo.createNode("merge", "abc_merge")
        objmerge_pos=sn[0].position()
        merge.setPosition(hou.Vector2(objmerge_pos[0],objmerge_pos[1]-2))
        nunode=Geo.createNode("null", "OUT")
        nunode.setPosition(hou.Vector2(objmerge_pos[0], objmerge_pos[1] - 4))
        for i in range(len(sn)):
            merge.setInput(i, sn[i])

        nunode.setInput(0,merge)
        nunode.setGenericFlag(hou.nodeFlag.Display,1)
        return Geo

    def _import_file(self):
        """
        import select file from local path
        :return:
        """
        if self.current_selected_path:
            ordir,file_name=os.path.split(self.current_selected_path)
            if file_name.endswith('.fbx'):
                dir_path=os.path.join(hou.getenv('JOB'),'fbx')
            else:# file_name.endswith('.abc'):
                dir_path=os.path.join(hou.getenv('JOB'),'abc')

            if dir_path:
                new_path = os.path.join(dir_path, file_name)
                print(new_path)
                if new_path.endswith('fbx'):
                    fbx=hou.hipFile.importFBX(new_path)
                    fbx.setPosition(hou.Vector2(10.6912, 15.3134))
                    try:
                        hou.item('/obj/Asset').addNode(fbx)
                    except Exception as item_add_ERR:
                        print(str(item_add_ERR))
                    QMessageBox.information(None, 'import', '导入完成')
                elif new_path.endswith('abc'):
                    abc=self._create_abc(new_path)
                    abc.setGenericFlag(hou.nodeFlag.Display, 0)
                    abc.setPosition(hou.Vector2(4.04098, 15.4192))
                    merge=self._create_abc_merge(abc)
                    try:
                        hou.item('/obj/Asset').addNode(abc)
                        hou.item('/obj/Asset').addNode(merge)
                    except Exception as item_add_ERR:
                        print(str(item_add_ERR))
                    QMessageBox.information(None, 'import', '导入完成')


class GlobalControl(QWidget):
    """
    主界面,操作方式，选择项目、集数、阶段、任务名称、然后获取到镜头信息，
    之后可以打开相关阶段窗口，获取跟踪与动画的文件，下载到本地，然后导入进houdini

    使用Open file可以打开hip栏当前的文件
    使用Save\Create File可以打开或者保存hip文件
    使用Save File (update version)可以自动递增版本保存文件
    使用Set Frame可以设置houdini的当前帧范围
    使用Set Frame Offset 1000在当前镜头长度帧范围内同时增加1000的基数值，用于电影镜头。
    使用Set FPS可以设置houdini当前工程的帧速率。
    Shot Info文本框里显示的是该镜头的相关信息。

    """
    def __init__(self):
        super(GlobalControl, self).__init__()
        self.HOST = '192.168.1.222'
        self.PORT = 4455
        self.BUFFER = 20480
        self.current_project = ''  # current selected project
        self.current_eps = ''  # current selected eps
        self.current_artists = []  # 当前部门人员
        self.current_shot = ''  # current selected shot
        self.asset_data = {}   # 该人员的所有任务
        self.current_pipeline = ''  # current selected pipeline
        self.current_resolution = '' #current selected shot resolution
        # self.setWindowFlags(Qt.FramelessWindowHint)
        self.request_project_info={}  #request project infomation data
        self.current_project_data={}  #current selected project info #{'database': 'proj_fndh', 'entity_name': 'FNDH', 'full_name': '涉过愤怒的海', 'eps_list': 'test|FNDH58|FNDH60|FNDH61|FNDH62|FNDH63|FNDH65|FNDH66|FNDH67|FNDH68|FNDH69|FNDH70|FNDH72|FNDH73|FNDH75|FNDH76|FNDH78|FNDH83|FNDH84|FNDH85|FNDH88|FNDH89|FNDH90|FNDH91|FNDH92|FNDH93|FNDH94|FNDH95|FNDH96|FNDH97|FNDH98|FNDH100|FNDH101|FNDH102|FNDH103|FNDH104|FNDH105|FNDH99|FNDH02', 'fps': '24'}
        self.current_project_config = {} #{'fps':'24','color': '#f6e7aa','resolution' :'3840x2160','path':'\\\\192.168.1.238\\cgteamwork5\\FNDH','full_name':'涉过愤怒的海', 'entity_name':'FNDH'}
        self.current_shot_info = {}  # current shot info  #{'description': '加鱼，雨，换天，路面做湿', 'entity_name': 'FNDH100_0020_01', 'img_path': '/upload/image/proj_fndh/min/51088c52f282cc9c971dd0bd767b300c.png', 'frame': '63'}

        self.btn_style= """QPushButton{color:black}
                                  QPushButton:hover{color:red}
                                 QPushButton{background-color:#A9A9A9}
                                  QPushButton{border:2px}
                                  QPushButton{border-radius:3px}
                                  QPushButton{padding:1px 1px}"""

        self.setWindowTitle('GlobalControl')
        self.main_layout = QVBoxLayout()
        self.main_layout.setSpacing(15)

        self.drive_layout=QHBoxLayout()
        self.drive_label=QLabel('Drive:')
        self.drive_btn=QPushButton(r'//192.168.8.2/fx')
        self.drive_btn.clicked.connect(self._drive_changed)
        self.drive_btn.setStyleSheet(self.btn_style)
        # self.drive_comb=QComboBox()
        # self.init_comb()
        # self.drive_comb.currentTextChanged.connect(self._drive_changed)

        self.drive_layout.addWidget(self.drive_label)
        self.drive_layout.addWidget(self.drive_btn)
        self.project_layout = QHBoxLayout()
        self.project_label = QLabel('Project:')
        self.choose_project_btn = QPushButton('- -')
        self.choose_project_btn.setStyleSheet(self.btn_style)
        self.choose_project_btn.clicked.connect(self._open_project_window)
        self.project_layout.addWidget(self.project_label)
        self.project_layout.addWidget(self.choose_project_btn)
        self.eps_layout = QHBoxLayout()
        self.eps_label = QLabel('Eps:')
        self.eps_comb = QComboBox()
        self.eps_comb.currentTextChanged.connect(self._eps_changed)
        self.eps_layout.addWidget(self.eps_label)
        self.eps_layout.addWidget(self.eps_comb)
        self.artists_layout = QHBoxLayout()
        self.artists_label = QLabel('Artist(资产必选):')
        self.artists_label.setVisible(False)
        self.artists_comb = QComboBox()
        self.artists_comb.setVisible(False)
        self.artists_comb.currentTextChanged.connect(self._artist_changed)
        self.artists_layout.addWidget(self.artists_label)
        self.artists_layout.addWidget(self.artists_comb)
        self.shot_layout = QHBoxLayout()
        self.shot_label = QLabel('Shot:')
        self.shot_list_btn=QPushButton('- -')
        self.shot_list_btn.clicked.connect(self._open_shot_window)
        self.shot_list_btn.setStyleSheet(self.btn_style)
        self.shot_layout.addWidget(self.shot_label)
        self.shot_layout.addWidget(self.shot_list_btn)
        self.pipeline_layout = QHBoxLayout()
        self.pipeline_label = QLabel('pipeline:')
        self.pipeline_comb = QComboBox()
        self.pipeline_layout.addWidget(self.pipeline_label)
        self.pipeline_layout.addWidget(self.pipeline_comb)
        self.init_pipeline_comb()
        self.pipeline_comb.currentTextChanged.connect(self._pipeline_changed)
        self.hip_layout=QHBoxLayout()
        self.hip_label=QLabel('hip:')
        self.hip_list_comb=QComboBox()
        # self.init_hip_comb()
        self.hip_layout.addWidget(self.hip_label)
        self.hip_layout.addWidget(self.hip_list_comb)
        self.relative_layout = QHBoxLayout()
        self.relative_label = QLabel('Relative:')
        self.relative_btn = QPushButton('open relative window')
        self.relative_btn.setStyleSheet(self.btn_style)
        self.relative_btn.clicked.connect(self._open_relative_window)
        self.relative_layout.addWidget(self.relative_label)
        self.relative_layout.addWidget(self.relative_btn)

        self.open_hip_dir_layout = QHBoxLayout()
        # self.open_dir_label = QLabel('Show in Explore')
        self.open_hip_dir_btn = QPushButton('Show in Explore')
        self.open_hip_dir_btn.clicked.connect(self._open_hip_dir)
        self.open_hip_dir_layout.addWidget(self.open_hip_dir_btn)

        self.save_layout = QHBoxLayout()
        self.save_layout.setContentsMargins(10, 20, 10, 5)
        self.save_layout.setSpacing(25)
        self.open_btn=QPushButton('Open File')
        self.open_btn.clicked.connect(self._open_file)
        self.save_btn = QPushButton('Save\Create File')
        self.save_btn.clicked.connect(self._save_file)
        self.version_save_btn = QPushButton('Save File (update version)')
        self.version_save_btn.clicked.connect(self._save_update)
        self.save_layout.addWidget(self.open_btn)
        self.save_layout.addWidget(self.save_btn)
        self.save_layout.addWidget(self.version_save_btn)

        self.set_layout = QHBoxLayout()
        self.set_frame_btn = QPushButton('Set Frame')
        self.set_frame_btn.clicked.connect(self._set_frame)
        self.set_1000frame_btn=QPushButton('Set Frame Offset 1000')
        self.set_1000frame_btn.clicked.connect(self._set_1000frame)
        self.set_fps_btn = QPushButton('Set FPS')
        self.set_fps_btn.clicked.connect(self._set_fps)
        self.set_layout.addWidget(self.set_frame_btn)
        self.set_layout.addWidget(self.set_1000frame_btn)
        self.set_layout.addWidget(self.set_fps_btn)

        self.import_layout = QVBoxLayout()
        self.import_cam_btn = QPushButton('Import Camera')
        self.import_ani_btn = QPushButton('Import Animation')

        self.text_layout = QVBoxLayout()
        self.text_label = QLabel('Shot Info:')
        self.text_brower = QTextBrowser()
        self.text_layout.addWidget(self.text_label)
        self.text_layout.addWidget(self.text_brower)

        self.main_layout.addLayout(self.drive_layout)
        self.main_layout.addLayout(self.project_layout)
        self.main_layout.addLayout(self.eps_layout)
        self.main_layout.addLayout(self.artists_layout)
        self.main_layout.addLayout(self.shot_layout)
        self.main_layout.addLayout(self.pipeline_layout)
        self.main_layout.addLayout(self.hip_layout)
        self.main_layout.addLayout(self.relative_layout)
        self.main_layout.addLayout(self.open_hip_dir_layout)
        self.main_layout.addLayout(self.save_layout)
        self.main_layout.addLayout(self.set_layout)
        self.main_layout.addLayout(self.import_layout)
        self.main_layout.addLayout(self.text_layout)

        self.setLayout(self.main_layout)


    def update_context(self):
        """
        更新全局项目路径,在打开，保存工程后进行。
        """
        dirve_dir = self.drive_btn.text()
        # dirve_dir = dirve_dir if not dirve_dir.endswith('/') else dirve_dir[:-1]
        project = self.choose_project_btn.text()
        eps = self.eps_comb.currentText()
        shot = self.shot_list_btn.text()
        task_name = self.pipeline_comb.currentText()
        job = r'{}/{}/{}/{}/{}'.format(dirve_dir, project, eps, shot, task_name).replace('://', ':/')
        hprefix = '_'.join([project, eps, shot, task_name])

        hou.setContextOption('drive',dirve_dir)
        hou.setContextOption('project',project)
        hou.setContextOption('eps',eps)
        hou.setContextOption('shot',shot)
        hou.setContextOption('task_name',task_name)
        hou.setContextOption('hprefix',hprefix)
        hou.setContextOption('job',job)

        hou.putenv('JOB',job)


    def init_comb(self):
        """
        init drive letter
        :return:
        """
        drive_list=['ip...','A:\\','B:\\','C:\\','D:\\','E:\\','F:\\','G:\\','H:\\','I:\\','J:\\','K:\\','L:\\','M:\\','N:\\','O:\\','P:\\','Q:\\','R:\\','S:\\','T:\\',
                    'U:\\','V:\\','W:\\','X:\\','Y:\\','Z:\\']
        self.drive_comb.addItems(drive_list)
        self.drive_comb.setCurrentText('E:')

    def request_from_222(self,msg):
        """
        request data from 222
        :param msg: {'ask_type':xxx,''}
        :return:
        """

        # print(msg)

        print(msg)

        data={}
        sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        sock.settimeout(0.35)
        try:
            sock.connect((self.HOST,self.PORT))
            sock.send(str(msg).encode())
            all_backs = b''
            while True:
                #time.sleep(0.1)
                print('接收中....')
                back = sock.recv(self.BUFFER)  # socket.MSG_WAITALL#,socket.MSG_WAITALL
                # # header_len=struct.unpack(back)

                #print('接受回来:')

                #print('接受回来:', back)
                print('接受回来')

                if not back:
                    break
                all_backs += back


        except Exception as request_from_222_ERR:
            print('request failed')
            print(str(request_from_222_ERR))
        finally:
            data = eval(all_backs.decode('utf8'))

            # print(data)

            #print(data)

            sock.close()

        return data

    def create_shot(self,path,shot_info):
        """
        create project
        :param path: dir path
        :param shot_info: current shot infomation
        :return:
        """
        pipeline = self.pipeline_comb.currentText()
        if not os.path.exists(path):
            os.makedirs(path)
        dir_list = ['hip', 'geo', 'cam', 'abc', 'tex', 'fbx', 'img', 'nk', 'hda', 'DCC', 'deadline']
        for i in dir_list:
            dirs_path = os.path.join(path, i)
            if not os.path.exists(dirs_path):
                os.makedirs(dirs_path)
        if pipeline == 'cfx':
            maya_dir_path = os.path.join(path, 'maya')
            if not os.path.exists(maya_dir_path):
                os.makedirs(maya_dir_path)
            maya_list = ['assets','autosave','clips','data','images','movies','renderData','sceneAssembly','scenes',
                         'scripts','sound','sourceimages','Time Editor','cache','haircache']
            for o in maya_list:
                folder_path = os.path.join(maya_dir_path,o)
                if not os.path.exists(folder_path):
                    os.makedirs(folder_path)

        # #最后将该镜头的信息写入
        # shot_info_path=os.path.join(path,'shot.info')
        # with open(shot_info_path,'w',encoding='utf8') as w:
        #     w.write(str(shot_info))


    def _drive_changed(self):
        dir = QFileDialog.getExistingDirectory(self, '选择目录')
        print(dir)
        self.drive_btn.setText(dir)
        hou.setContextOption('drive',dir)

    def _open_project_window(self):
        """
        request 222 get project infomation
        :return:
        """
        self.project_list_window = ListModel()
        self.project_list_window.data_Signal.connect(self._get_project_info)
        msg = {'ask_type': 'project'}
        data = self.request_from_222(msg)
        self.project_list_window.set_data(data)
        self.project_list_window.show()

    def _get_project_info(self,data):
        self.current_project_data = data
        project_entity_name = data['entity_name']
        # print('_get_project_info:',data)
        msg = {'ask_type': 'config', 'entity_name': project_entity_name}
        self.current_project_config = self.request_from_222(msg)
        self.current_project_config = self.current_project_config if self.current_project_config != 404 else {'fps': '',
                                                                                                              'color': '',
                                                                                                              'resolution': '',
                                                                                                              'path': '',
                                                                                                              'full_name': '',
                                                                                                              'entity_name': ''}
        # print('_get_project_info  self.current_project_data:',self.current_project_data)
        # print('_get_project_info  self.current_project_config:',self.current_project_config)
        self.choose_project_btn.setText(project_entity_name)
        try:
            hou.setContextOption('project', project_entity_name)
        except Exception as Test:
            print('setContextOption testing')
        eps_list = data['eps_list'].split('|')

        self.init_eps_comb(eps_list)

    def _eps_changed(self,current_eps):
        self.shot_list_btn.setText('- -')
        if current_eps == 'Asset':
            self.artists_label.setVisible(True)
            self.artists_comb.setVisible(True)
            msg = {'ask_type':'account','cn_department':'特效'} #这个仅给特效，写死
            artists_data = self.request_from_222(str(msg))
            self.current_artists = artists_data.get('artists',[])
            self.current_artists.insert(0,'')
            # print('current_artists:',self.current_artists)
            self.artists_comb.clear()
            self.artists_comb.addItems(self.current_artists)
        else:
            self.artists_label.setVisible(False)
            self.artists_comb.setVisible(False)

        try:
            hou.setContextOption('eps', current_eps)
        except Exception as Test:
            print('_eps_changed testing')

    def _artist_changed(self,artist):
        print('current artist:',artist)
        self.shot_list_btn.setText('- -')
        msg = {'ask_type': 'artist_assets', 'database': self.current_project_data['database'],'artist':artist}
        asset_datas = self.request_from_222(str(msg))
        # print('asset_datas:',asset_datas)
        self.asset_data = asset_datas if asset_datas !=404 else {}

    def _pipeline_changed(self,pipeline):
        self.init_hip_comb()
        hou.setContextOption('task_name', pipeline)

    # def _open_shot_window_Ori(self):
    #     """
    #     request 222, get shot info
    #     :return:
    #     """
    #     #print('_open_shot_window:',self.current_project_data)
    #     print('_open_shot_window:')
    #     if self.current_project_data:
    #         database = self.current_project_data['database']
    #         eps=self.eps_comb.currentText()
    #
    #         self.shot_info_window=ShotListWindow()
    #         self.shot_info_window.shot_Signal.connect(self._get_shot_info)
    #         msg = {'ask_type': 'shot','database':database,'eps':eps}
    #         print(msg)
    #         data = {}
    #             # msg = {'ask_type': 'asset', 'database': database, 'eps': eps}
    #         if eps != 'Asset':
    #             data=self.request_from_222(msg)
    #
    #         else:
    #             drive = self.drive_btn.text()
    #             project = self.choose_project_btn.text()
    #             if project != '- -':
    #                 asset_path = os.path.join(drive, project, 'Asset')
    #                 if os.path.exists(asset_path):
    #                     shot_dirs=os.listdir(asset_path)
    #                     for d in shot_dirs:
    #                         data[d]={'description': '', 'entity_name': d, 'img_path': 'path', 'frame': '100'}
    #         self.shot_info_window.set_data(data)
    #         self.shot_info_window.show()

    def _open_shot_window(self):
        """
        request 222, get shot info
        :return:
        """
        if self.current_project_data:
            database = self.current_project_data['database']
            eps = self.eps_comb.currentText()


            msg = {'ask_type': 'shot','database':database,'eps':eps}
            print(msg)
            data = {}
                # msg = {'ask_type': 'asset', 'database': database, 'eps': eps}
            if eps != 'Asset':

                data=self.request_from_222(msg)

            else:
                for v in self.asset_data.values():
                    entity_name = v['entity_name']
                    data[entity_name] = v

            self.shot_info_window=ShotListWindow()
            self.shot_info_window.shot_Signal.connect(self._get_shot_info)
            self.shot_info_window.set_data(data)
            self.shot_info_window.show()




    def _get_shot_info(self,data):
        """
        slot back shot data
        :param data:
        :return:
        """
        self.current_shot_info=data
        self.current_resolution = data.get('resolution', self.current_project_config['resolution'])
        shot_name = data['entity_name']
        self.shot_list_btn.setText(shot_name)
        hou.setContextOption('shot', shot_name)
        self._show_shot_info()#self.current_shot_info
        self.init_hip_comb()


    def get_relative_data(self,cgtw_path,eps,shot_name,pipeline):
        data={}
        if pipeline=='mm':
            path = os.path.join(cgtw_path, 'Shot_work', 'Matchmove', eps)
            data = {}
            abc_path = os.path.join(path, 'abc')
            if os.path.exists(abc_path): #get fbx
                # file_list = os.listdir(path)
                print('path:',path)
                print('abc_path:',abc_path)
                # if os.path.exists(abc_path):
                file_list = os.listdir(abc_path)
                for i in file_list:
                    name=i.split('_mm')[0]
                    # if shot_name == name and i.endswith('.fbx') and not i.startswith('.'):
                    if shot_name == name and i.endswith('.abc') and not i.startswith('.'):
                        data[i] = os.path.join(abc_path, i)
            # data[pipeline] = data
        if pipeline=='ani':
            path = os.path.join(cgtw_path, 'Shot_work', 'Animation', eps,shot_name,'maya_file')
            data = {}
            if os.path.exists(path):
                file_list = os.listdir(path)
                for i in file_list:  #
                    name = i.split('_ani')[0]  #
                    if shot_name == name or i.endswith('.ma') or i.endswith('.abc') and not i.startswith('.'):
                        data[i] = os.path.join(path, i)
        if pipeline=='abc': #这里获取abc文件目录
            path = os.path.join(cgtw_path, 'Shot_work', 'Animation', eps,shot_name,'abc')
            data = {}
            if os.path.exists(path):
                dir_list = os.listdir(path)#这里是文件夹列表
                for i in dir_list:
                    name = i.split('_ani')[0]
                    if shot_name == name: # or i.endswith('.ma') or i.endswith('.abc') and not i.startswith('.'):
                        data[i] = os.path.join(path, i)

        if pipeline=='env':
            path = os.path.join(cgtw_path, 'Shot_work', 'Environment', eps,'Render')
            data = {}
            if os.path.exists(path):
                file_list = os.listdir(path)
                for i in file_list:
                    name = i.split('_env')[0]
                    if shot_name == name and not i.startswith('.'):
                        data[i] = os.path.join(path, i)
            # data[pipeline] = data
        return data

    def _open_relative_window(self):
        if self.current_project_data and self.current_project_config:
            # print('self.current_shot_info:',self.current_shot_info)
            data={}
            cgtw_path=self.current_project_config['path']
            project_name=self.choose_project_btn.text()
            eps=self.eps_comb.currentText()
            shot_name=self.shot_list_btn.text()
            mm_data=self.get_relative_data(cgtw_path,eps,shot_name,'mm')
            ani_data=self.get_relative_data(cgtw_path,eps,shot_name,'ani')
            abc_data=self.get_relative_data(cgtw_path,eps,shot_name,'abc')
            env_data=self.get_relative_data(cgtw_path,eps,shot_name,'env')
            data['mm']=mm_data
            data['ani']=ani_data
            data['abc']=abc_data
            data['env']=env_data


            self.relative_window=PipelineTab()
            self.relative_window.init_pipeline_source(data)
            self.relative_window.show()

    def init_config(self, config_path):
        config_data = {}
        if os.path.exists(config_path):
            with open(config_path, 'r') as r:  # ,encoding='utf8'
                config_data = eval(r.read())
        #print('config_data:', config_data)
        return config_data

    def init_data(self, path):
        data = {}
        if os.path.exists(path):
            with open(path, 'r', encoding='utf8') as r:  # ,encoding='utf8'
                data = eval(r.read())
        #print('data:', data)
        return data

    def init_project_comb(self, data):
        """
        init project_comb items
        :param data:
        :return:
        """
        if data:
            self.project_comb.clear()
            self.project_comb.addItems(sorted(list(data.keys())))

    def init_eps_comb(self,eps_list):
        """
        init eps items
        :return:
        """
        self.eps_comb.clear()
        s_list=sorted(eps_list)
        s_list.insert(0,'Asset')
        s_list.insert(0,'')
        self.eps_comb.addItems(s_list)
        self.current_eps = self.eps_comb.currentText()


    def init_shot_comb(self):
        """
        init shot comb items
        :return:
        """
        current_project = self.project_comb.currentText()
        current_eps = self.eps_comb.currentText()
        if current_project and current_eps:
            shot_dir = os.path.join(self.project_root_path, current_project, current_eps)
            if os.path.exists(shot_dir):
                shot_list = os.listdir(shot_dir)
                self.shot_comb.clear()
                self.shot_comb.addItems(sorted(shot_list))

    def init_pipeline_comb(self):
        # pipeline_list=['efx','efx_crowd','efx_hero','efx_cloth','efx_hair']
        pipeline_list = ['efx','cfx']
        self.pipeline_comb.addItems(pipeline_list)

    def init_hip_comb(self):
        self.hip_list_comb.clear()
        hip_list = []
        drive = self.drive_btn.text()
        project = self.choose_project_btn.text()
        eps = self.eps_comb.currentText()
        shot = self.shot_list_btn.text()
        pipeline = self.pipeline_comb.currentText()
        if project != '- -' and shot != '- -' and eps:
            dir_path = os.path.join(drive, project, eps, shot, pipeline,'hip')
            if os.path.exists(dir_path):
                f_list=os.listdir(dir_path)
                for i in f_list:
                    if i.endswith('.hip'):
                        hip_list.append(i)
        self.hip_list_comb.addItems(hip_list)


    def _show_shot_info(self):#, shot_info
        """
        pipeline changed  update the shot info
        :return:
        """
        # show_text = ''
        if self.current_shot_info:
            # print(shot_info)
            show_text ='项目: {}'.format(self.current_project_data.get('full_name',''))+'\n'+'FPS: {}'.format(self.current_project_data.get('fps',''))+'\n' \
                        +'分辨率: {}'.format(self.current_resolution)+'\n'+'项目路径: {}'.format(self.current_project_config.get('path',''))+'\n'\
                       +'帧数: {}'.format(self.current_shot_info.get('frame','')+'\n' + '制作内容: {}'.format(self.current_shot_info['description']))
            self.text_brower.setText(show_text)




    def _open_file(self):
        """
        open existed hip
        :return:
        """
        drive=self.drive_btn.text()
        project=self.choose_project_btn.text()
        eps=self.eps_comb.currentText()
        shot=self.shot_list_btn.text()
        pipeline=self.pipeline_comb.currentText()
        hip_name=self.hip_list_comb.currentText()
        if project!='- -' and shot!='- -' and eps and hip_name:
            dir_path = os.path.join(drive, project, eps, shot, pipeline)
            hip_path = os.path.join(dir_path,'hip',hip_name)
            hou.hipFile.load(hip_path.replace('\\','/'))
            self.update_context()

    def save_new_file(self, new_name):
        """
        slot from name window ,save new file
        :param new_name:
        :return:
        """

        drive = self.drive_btn.text()
        project = self.choose_project_btn.text()
        eps = self.eps_comb.currentText()
        shot = self.shot_list_btn.text()
        pipeline = self.pipeline_comb.currentText()
        if project != '- -' and shot != '- -' and eps:
            dir_path = os.path.join(drive, project, eps, shot, pipeline)
            hip_name = shot + '_' + pipeline + '_' + new_name + '_v001.hip'  # project+'_'+eps+'_'+
            hip_path = os.path.join(dir_path, 'hip', hip_name)  # 如果存在该文件，那么自增长
            if os.path.exists(hip_path):
                new_hip_name = self.update_version(hip_name)
                hip_path = os.path.join(dir_path, new_hip_name)
            self.create_shot(dir_path,self.current_shot_info)
            hou.hipFile.save(hip_path.replace('\\','/'))
            self.update_context()



    def _save_file(self):
        """
        save current hip to the path as its shot name
        :return:
        """
        new_file = ''
        # current_shot_name=self.current_shot.currentText()
        self.name_window = Name()
        self.name_window.name_Signal.connect(self.save_new_file)
        self.name_window.show()

    def int2str(self,number):
        if number < 10:
            return 'v00' + str(number)
        elif number < 100:
            return 'v0' + str(number)
        else:
            return 'v' + str(number)

    def update_version(self,ori_version):
        new_file_name = ''
        file_name, ex_name = os.path.splitext(ori_version)
        slite_files = file_name.split('_')
        vers = slite_files[-1]
        slite_files.remove(vers)
        if vers.startswith('v'):
            num = vers[1:]
            new_ver = int(num) + 1
            version = self.int2str(new_ver)
            slite_files.append(version)
            new_file_name = '_'.join(slite_files) + ex_name
        else:
            new_file_name = file_name + '_v001' + ex_name
        return new_file_name


    def _open_hip_dir(self):
        hip_path = hou.hipFile.name()
        try:
            os.startfile(os.path.dirname(hip_path))
        except Exception as _open_hip_dir_ERR:
            print('_open_hip_dir_ERR:',_open_hip_dir_ERR)

    def _save_update(self):
        """
        autosave file update version
        """
        new_file = ''
        current_file_name = hou.getenv('HIPFILE')#hou.hipFile.name()

        if current_file_name == 'untitled.hip':
            pass
        else:
            dir_path, hip_name = os.path.split(current_file_name)
            new_hip_name=self.update_version(hip_name)
            new_file=os.path.join(dir_path,new_hip_name)

        if new_file:
            if os.path.exists(new_file):
                self.ex_window=ExistDialog(new_file)
                self.ex_window.show()
            else:
                hou.hipFile.save(new_file)

    def _set_frame(self):
        """
        set the frame of current hip
        :return:
        """
        if self.current_shot_info:
            frame = self.current_shot_info['frame']
            hou.playbar.setFrameRange(1, int(frame))
            hou.playbar.setPlaybackRange(1, int(frame))

    def _set_1000frame(self):
        """
        set the frame of current hip
        :return:
        """
        if self.current_shot_info:
            frame = self.current_shot_info['frame']
            hou.playbar.setFrameRange(1001, 1000+int(frame))
            hou.playbar.setPlaybackRange(1001, 1000 + int(frame))

    def _set_fps(self):
        """
        set current fps
        :return:
        """
        if self.current_project_data:
            fps = self.current_project_data['fps']
            hou.setFps(int(fps))


def onCreateInterface():
    widget = GlobalControl()
    return widget


if __name__ == '__main__':
    app = QApplication(sys.argv)

    g = GlobalControl()
    g.show()
    sys.exit(app.exec_())









